package com.ffs.lock;

import java.util.concurrent.locks.ReentrantLock;

/**
 * 对象锁
 *
 * @author ffs80 created 2021/7/2
 */
public class ObjectLock extends ReentrantLock implements Comparable<ObjectLock> {

    private static final Class<IEntity> I_ENTITY_CLASS = IEntity.class;

    private final Class<?> clazz;

    private final Comparable value;

    private final boolean entity;

    public ObjectLock(Object object) {
        this(object, false);
    }

    public ObjectLock(Object object, boolean fair) {
        super(fair);
        this.clazz = object.getClass();
        if (object instanceof IEntity) {
            this.value = ((IEntity<?>) object).getIdentity();
        } else {
            this.value = new Integer(System.identityHashCode(object));
        }
        if (I_ENTITY_CLASS.isAssignableFrom(this.clazz)) {
            this.entity = true;
        } else {
            this.entity = false;
        }
    }

    /**
     * 判断是否为同一对象（同一对象使用重入锁）
     */
    public boolean isTie(ObjectLock other) {
        if (this.clazz != other.clazz) {
            return false;
        }
        if (this.value.compareTo(other.value) == 0) {
            return true;
        }
        return false;
    }

    public Class<?> getClazz() {
        return clazz;
    }

    public Comparable getValue() {
        return value;
    }

    public boolean isEntity() {
        return entity;
    }

    @Override
    public int compareTo(ObjectLock o) {
        if (isEntity() && (!o.isEntity())) {
            return 1;
        }
        if ((!isEntity()) && (o.isEntity())) {
            return -1;
        }
        if (this.clazz != o.clazz) {
            if (this.clazz.hashCode() < o.clazz.hashCode()) {
                return -1;
            }
            if (this.clazz.hashCode() > o.clazz.hashCode()) {
                return 1;
            }
            return this.clazz.getName().compareTo(o.clazz.getName());
        }

        return this.value.compareTo(o.value);
    }
}

